<!DOCTYPE html>
<html lang="en">
<head>
    <title>Openfire: Pluggable Roster Support Guide</title>
    <link href="style.css" rel="stylesheet" type="text/css">
</head>
<body>

<article>

    <header>
        <img src="images/header_logo.gif" alt="Openfire Logo" />
        <h1>Pluggable Roster Support Guide</h1>
    </header>

    <nav>
        <a href="index.html">&laquo; Back to documentation index</a>
    </nav>

    <section id="intro">

        <h2>Introduction</h2>

        <p>
            This document provides instructions on how to configure Openfire's roster support to work
            with alternate sources of roster data rather than the provided database tables.
        </p>
        <p>
            This integration requires some Java knowledge in order to implement a custom roster provider
            for Openfire. The skill needed will vary depending on what you are trying to achieve.
            The extension approach is similar to the
            <a href="implementing-authprovider-guide.html">custom AuthProvider approach</a> on which it is based.
        </p>

        <p>Topics that are covered in this document:</p>

        <nav>
            <ul>
                <li><a href="#background">Background</a>
                <li><a href="#rosteritem">The RosterItemProvider extension point</a>
                <li><a href="#faq">Frequently Asked Questions</a>
            </ul>
        </nav>

    </section>

    <section id="background">

        <h2>Background</h2>

        <p>
            Consider the scenario where Openfire is integrated as the chat server solution for an existing
            'social' application. In this application a user is linked to other users via a relationship
            of sorts, and the system of record for the relationship data is NOT the Openfire system.
            Using an XMPP server such as Openfire the applications benefit from the real-time nature of
            XMPP rosters and other subscription based features such as PEP, but with the caveat that
            the existing relationship information has to be duplicated in Openfire and could potentially
            become out of sync.
        </p>
        <p>
            With the introduction of pluggable roster providers, Openfire can be instructed to retrieve and
            modify roster data that lives in alternative locations to the standard database tables. The options
            are limitless as to what this could be, e.g. an alternative database table(s), a web service, a NoSQL
            database etc.
        </p>

    </section>

    <section id="rosteritem">

        <h2>The RosterItemProvider extension point</h2>

        <p>
            As of Openfire 3.7.2, the class RosterItemProvider has changed from being a concrete class to an interface.
            The default implementation of this provider is the DefaultRosterItemProvider, which as the name suggests is the
            version of this provider Openfire will use if not overridden. The DefaultRosterItemProvider uses the Openfire
            database to retrieve roster information.
        </p>
        <p>
           The steps to get Openfire using a custom RosterItemProvider are described below.
        </p>
        <ol>
            <li>
                Write a class that implements RosterItemProvider, providing your own business logic.
            </li>
            <li>
                Make the class available in a jar and make this available to Openfire by placing it in the lib directory.
                Why not use an Openfire plugin, you ask? Read the FAQ entry below! There are numerous ways to package a
                jar with this class inside it, popular build systems such as Gradle and Maven can make your life easier.
            </li>
            <li>
                Set the property 'provider.roster.className' to be the full name of your class, e.g. 'com.foo.bar.MyRosterItemProvider'.
            </li>
            <li>
                Restart Openfire. Your custom class should now be handling all the roster based operations.
            </li>
        </ol>

    </section>

    <section id="faq">

        <h2>Frequently Asked Questions</h2>

        <h4>Do I have to compile my custom class into the Openfire jar?</h4>
        <p>
            No, the class only needs to be visible on the Openfire classpath.
        </p>

        <h4>How do I ensure my custom class is visible on the Openfire classpath?</h4>
        <p>
            Just place your new custom library in the Openfire lib directory, this will ensure it is automatically
            available at startup.
        </p>

        <h4>Should I include all the dependencies that my code needs?</h4>
        <p>
            Yes, and no. Your code will run using the same classpath as Openfire. Openfire's dependencies are already on
            that classpath. If your code uses the same dependencies, you do not need to include them again. You can add
            other dependencies, either by packaging them in your jar file, or by placing them in the openfire lib folder.
        </p>
        <p>
            Beware of conflicting dependencies! Sometimes, packaging dependencies in an all-containing jar, and renaming
            the packages of those dependencies (<em>shade</em> them), can be helpful.
        </p>

        <h4>Isn't it easier to deploy my code as an Openfire plugin?</h4>
        <p>
            It is not recommended to use a plugin for packaging and deploying your provider. For one, plugins use a
            dedicated class path. For another, the load order of plugins could lead to hairy scenarios, and finally:
            plugins can be <em>unloaded</em> at runtime. This all could lead to a running Openfire service for which you
            cannot guarantee that your provider is loaded at all times. For these reasons, we recommend creating a jar
            file instead of an Openfire plugin, and placing that jar file in Openfire's lib directory!
        </p>

        <h4>Will I have a degradation in performance using a custom RosterItemProvider?</h4>
        <p>
            It completely depends on your implementation. As with any Openfire customisation or plugin, badly written
            code has the potential to cause Openfire to perform slower. Use performance testing tools such as Tsung to
            ensure issues haven't been introduced.
        </p>

        <h4>How can I have my custom class connect to another DB/Web service/NoSQL store etc?</h4>
        <p>
            This is out of the scope of this documentation and is your choice as a developer. If you are looking to
            externalize properties like connection details, the Openfire properties mechanism and the JiveGlobals class
            are good places to start investigating.
        </p>

        <h4>Can I have multiple RosterItemProviders, in a similar vein to the HybridAuthProvider?</h4>
        <p>
            No, this feature is currently not implemented. Get involved if you feel a need to have it!
        </p>

    </section>

    <footer>
        <p>
            An active support community for Openfire is available at
            <a href="https://discourse.igniterealtime.org">https://discourse.igniterealtime.org</a>.
        </p>
    </footer>

</article>

</body>
</html>
